import 'package:flutter/material.dart';
import 'package:flutterapp/common/base/base_mode.dart';
import 'package:provider/provider.dart';

/// provider基础类，用于配合base_page使用
class BaseProvider<T extends BaseModel> extends StatefulWidget {
  /// 数据模型类
  final T model;

  /// 构建方法,优先级高于childBuilder,默认提供model
  final Widget Function(BuildContext, T)? modelBuilder;

  /// 构建方法，优先级低于modelBuilder，子类可以通过context获取泛型T的model
  final Widget Function(BuildContext)? childBuilder;

  const BaseProvider(
      {Key? key, required this.model, this.modelBuilder, this.childBuilder})
      : super(key: key);

  @override
  _BaseProviderState<T> createState() => _BaseProviderState<T>();
}

class _BaseProviderState<M extends BaseModel> extends State<BaseProvider<M>> {
  /// 显示错误布局
  bool showErrorView = false;

  /// 显示加载布局
  bool showLoadingView = true;

  /// 组件销毁标识
  bool isDisposed = false;

  @override
  void initState() {
    super.initState();

    //第一帧
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      reLoading();
    });
  }

  @override
  void dispose() {
    super.dispose();

    isDisposed = true;
  }

  /// 组件刷新方法
  void update() {
    if (!isDisposed && mounted) {
      setState(() {});
    }
  }

  /// 页面重新载入方法
  void reLoading() async {
    //开启加载弹窗
    showLoadingView = true;
    update();
    //调用初始化方法,并关闭加载弹窗和判断是否展示错误页面
    bool value = await widget.model.init();
    showErrorView = !value;
    showLoadingView = false;
    update();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          //内容
          ChangeNotifierProvider(
            create: (BuildContext context) => widget.model,
            builder: widget.modelBuilder == null
                ? (context, child) =>
                    widget.childBuilder?.call(context) ?? Container()
                : (context, child) =>
                    widget.modelBuilder!(context, context.watch<M>()),
          ),
          //页面错误层(如网络错误、重试等)
          ErrorView(
            isShow: showErrorView,
            key: widget.model.errorViewKey,
            msg: '未查询到数据',
            onReload: () {
              reLoading();
            },
          ),
          //加载弹窗层
          LoadingView(
            showLoading: showLoadingView,
            key: widget.model.loadingViewKey,
          ),
        ],
      ),
    );
  }
}

/// 加载弹窗组件
class LoadingView extends StatefulWidget {
  /// 是否显示
  final bool showLoading;

  /// 加载弹窗显示的内容
  final String msg;

  const LoadingView({Key? key, this.showLoading = false, this.msg = '加载中...'})
      : super(key: key);

  @override
  LoadingViewState createState() => LoadingViewState();
}

class LoadingViewState extends State<LoadingView> {
  bool? _showLoading;
  String? _msg;

  @override
  void initState() {
    super.initState();

    _showLoading = widget.showLoading;
    _msg = widget.msg;
  }

  @override
  void didUpdateWidget(covariant LoadingView oldWidget) {
    super.didUpdateWidget(oldWidget);
    _showLoading = widget.showLoading;
    _msg = widget.msg;
  }

  /// 显示弹窗
  void show([String content = '加载中']) {
    if (!(_showLoading ?? false) || _msg != content) {
      setState(() {
        _showLoading = true;
        _msg = content;
      });
    }
  }

  /// 关闭弹窗
  void hide() {
    if (_showLoading ?? false) {
      setState(() {
        _showLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return //加载提示
        Visibility(
      visible: _showLoading ?? false,
      child: Container(
        alignment: Alignment.center,
        color: Colors.black.withOpacity(.5),
        child: Container(
          width: 100,
          height: 100,
          alignment: Alignment.center,
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Colors.grey[400],
            borderRadius: BorderRadius.circular(4),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              CircularProgressIndicator(),
              Padding(
                padding: const EdgeInsets.only(top: 12),
                child: Text(_msg ?? ''),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

/// 网络出错展示组件
class ErrorView extends StatefulWidget {
  /// 错误内容
  final String? msg;

  /// 重新加载
  final void Function()? onReload;

  /// 是否显示
  final bool isShow;

  /// 子类,可以用于自定义错误页面,上面[msg]、[onReload]属性将失效
  final Widget? errorChild;

  const ErrorView(
      {Key? key, this.msg, this.onReload, this.isShow = false, this.errorChild})
      : super(key: key);
  @override
  ErrorViewState createState() => ErrorViewState();
}

class ErrorViewState extends State<ErrorView> {
  bool? _isShow;
  String? _msg;
  void Function()? _onReload;

  @override
  void initState() {
    super.initState();

    _isShow = widget.isShow;
    _msg = widget.msg;
    _onReload = widget.onReload;
  }

  @override
  void didUpdateWidget(covariant ErrorView oldWidget) {
    super.didUpdateWidget(oldWidget);

    _isShow = widget.isShow;
    _msg = widget.msg;
    _onReload = widget.onReload;
  }

  /// 显示
  void show([String content = '']) {
    setState(() {
      _isShow = true;
      _msg = content;
    });
  }

  /// 隐藏
  void hide() {
    setState(() {
      _isShow = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Visibility(
      visible: _isShow ?? false,
      child: widget.errorChild ??
          Container(
            color: Colors.white,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Image.asset("images/net_error.png"),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(_msg ?? ''),
                ),
                Visibility(
                  visible: _onReload != null,
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: ElevatedButton(
                      child: Text(
                        '重新加载',
                      ),
                      onPressed: _onReload,
                    ),
                  ),
                )
              ],
            ),
          ),
    );
  }
}
